#include "chatlistform.h"

#include "data/UserInfo.pb.h"

#include <data/Message.pb.h>
using namespace proto;
#include "ui_chatlistform.h"

#include <Application.h>
#include <QDateTime>
#include <QDebug>
#include <QTimer>
#include <forms/mainwindow/WindowManager.h>
#include <vcruntime_typeinfo.h>

ChatListForm::ChatListForm(WindowManager* manager, QWidget* parent) : QWidget(parent),
                                                                      windowManager(*manager),
                                                                      ui(new Ui::ChatListForm) {
    ui->setupUi(this);
    init();
    ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);
}

ChatListForm::~ChatListForm() {
    delete ui;
}

void ChatListForm::onSetCurrent() {
}

void ChatListForm::init() {
    // 设置可拖拽
    ui->listWidget->setDragDropMode(QAbstractItemView::InternalMove);
    connect(ui->listWidget->model(), &QAbstractItemModel::rowsMoved, this, [this](const QModelIndex& parent, int start, int end, const QModelIndex& destination, int row) {
        qDebug() << "Rows moved from" << start << "to" << end << "to destination" << row;
    });

    auto app = Application::instance();

    //
    connect(app, &Application::signalMessage, this, &ChatListForm::onMessage);
    // connect(app, &Application::signalGetUserInfo, this, &ChatListForm::onGetUserInfo);

    connect(ui->listWidget, &QListWidget::itemClicked, this, &ChatListForm::onItemClicked);
    connect(ui->listWidget, &QListWidget::itemDoubleClicked, this, &ChatListForm::onItemDoubleClicked);

}

/**
 * @brief 处理并分发新收到的消息
 *
 * @param msg 新收到的消息
 */
void ChatListForm::onMessage(std::shared_ptr<::proto::data::Message> msg) {
    if (msg->type() == ::proto::data::Message::PTOP) {
        onMessagePTOP(msg);
    }
    else {
        onMessageGROUP(msg);
    }
}

/**
 * @brief 分发一对一聊天
 *
 * @param msg
 */
void ChatListForm::onMessagePTOP(std::shared_ptr<::proto::data::Message> msg) {
    try {
        auto talkWindow = talkWindows.at(QString::fromStdString(msg->from_user_id()));

        auto chatItem = chatItems.at(QString::fromStdString(msg->from_user_id()));

        auto& queueMessage = dendingMessages[QString::fromStdString(msg->from_user_id())];
        queueMessage.push(msg);

        while (!queueMessage.empty()) {
            auto msg = queueMessage.front();
            queueMessage.pop();
            talkWindow->onNewMessage(msg);

            auto now     = QDateTime::currentDateTime();
            auto msgTime = QDateTime::fromString(msg->time().c_str(), "yyyy-MM-dd hh:mm:ss");

            auto    days = msgTime.daysTo(now);
            QString time = msgTime.toString(days <= 0 ? "hh:mm" : "MM-dd");
            chatItem->setMessage(msg->text().c_str(), time);
        }
    }
    catch (const std::exception&) {
        auto& msgQueue = dendingMessages[QString::fromStdString(msg->from_user_id())];
        msgQueue.push(msg);
        // 未完成
    }
}

/**
 * @brief 分发群聊天
 *
 * @param msg
 */
void ChatListForm::onMessageGROUP(std::shared_ptr<::proto::data::Message> msg) {
        try {
        auto talkWindow = talkWindows.at(msg->to_user_id().c_str());

        auto chatItem = chatItems.at(msg->to_user_id().c_str());

        auto& queueMessage = dendingMessages[msg->to_user_id().c_str()];
        queueMessage.push(msg);

        while (!queueMessage.empty()) {
            auto msg = queueMessage.front();
            queueMessage.pop();
            talkWindow->onNewMessage(msg);

            auto now     = QDateTime::currentDateTime();
            auto msgTime = QDateTime::fromString(msg->time().c_str(), "yyyy-MM-dd hh:mm:ss");

            auto    days = msgTime.daysTo(now);
            QString time = msgTime.toString(days <= 0 ? "hh:mm" : "MM-dd");
            chatItem->setMessage(msg->text().c_str(), time);
        }
    }
    catch (const std::exception&) {
        auto& msgQueue = dendingMessages[msg->to_user_id().c_str()];
        msgQueue.push(msg);
        // 未完成
    }
}

void ChatListForm::onGetUserInfo(data::UserInfo userInfo, int code, QString message) {
    // talkWindows[userInfo.userid().c_str()] = new TalkWindow();

    // if (code == 0) {
    //     addNewChat(userInfo);

    //     QTimer* timer = new QTimer(this);
    //     connect(timer, &QTimer::timeout, [this, userInfo]() {
    //         auto* talkWindow = talkWindows[userInfo.userid().c_str()];

    //         auto& queueMessage = dendingMessages[userInfo.userid().c_str()];

    //         while (!queueMessage.empty()) {
    //             auto msg = queueMessage.front();
    //             queueMessage.pop();
    //             talkWindow->onNewMessage(msg);
    //         }
    //     });
    //     timer->start(2000);
    // }
}

void ChatListForm::onGetRoomInfo(data::ChatRoomInfo roomInfo, int code, QString message) {
    if (code == 0) {
        addNewChat(roomInfo);

        QTimer* timer = new QTimer(this);
        connect(timer, &QTimer::timeout, [this, roomInfo]() {
            auto* talkWindow = talkWindows[roomInfo.roomid().c_str()];

            auto& queueMessage = dendingMessages[roomInfo.roomid().c_str()];

            while (!queueMessage.empty()) {
                auto msg = queueMessage.front();
                queueMessage.pop();
                talkWindow->onNewMessage(msg);
            }
        });
        timer->start(2000);
    }
}
void ChatListForm::onItemClicked(QListWidgetItem* item) {
    QWidget*  widget   = ui->listWidget->itemWidget(item);
    ChatItem* userItem = static_cast<ChatItem*>(widget);

    auto userId     = userItem->getUserId();
    auto talkWindow = talkWindows[userId];
    windowManager.setCurrentWidget(talkWindow);
}
void ChatListForm::onItemDoubleClicked(QListWidgetItem* item) {
}

void ChatListForm::onTalkNewMessage(std::shared_ptr<::proto::data::Message> msg) {
    try {
        QString userId = QString::fromStdString(msg->from_user_id());
        if (msg->from_user_id() == Application::instance()->Myself().userid())
            userId = msg->to_user_id().c_str();

        auto chatItem = chatItems.at(userId);
        auto item     = items[userId];

        auto now     = QDateTime::currentDateTime();
        auto msgTime = QDateTime::fromString(msg->time().c_str(), "yyyy-MM-dd hh:mm:ss");

        auto    days = msgTime.daysTo(now);
        QString time = msgTime.toString(days <= 0 ? "hh:mm" : "MM-dd");

        auto row = ui->listWidget->row(item);
        // if (0) {
        if (row != 0) {
            auto newchatItem  = new ChatItem(ui->listWidget);
            chatItems[userId] = newchatItem;
            newchatItem->setName(chatItem->getName());
            newchatItem->setUserId(chatItem->getUserId());
            newchatItem->setPixmap(chatItem->getPixmp());
            newchatItem->setMessage(msg->text().c_str(), time);

            ui->listWidget->takeItem(row);
            ui->listWidget->insertItem(0, item);
            ui->listWidget->setItemWidget(item, newchatItem);
            ui->listWidget->setCurrentItem(item);
            delete chatItem;
        }
        else {
            ui->listWidget->setCurrentItem(item);
            chatItem->setMessage(msg->text().c_str(), time);
        }
    }
    catch (const std::exception& e) {
        qDebug() << e.what() << '\n';
    }
}

void ChatListForm::addNewChat(const data::FriendInfo& info) {
    try {
        auto* talkWindow = talkWindows.at(info.userid().c_str());
        windowManager.setCurrentWidget(talkWindow);
        auto* item = items[info.userid().c_str()];
        ui->listWidget->setCurrentItem(item);
    }
    catch (const std::exception&) {
        auto talkWindow = windowManager.addSubWindow<TalkWindow>(info.userid().c_str());
        talkWindow->setTitle(info.name().c_str());
        talkWindows[info.userid().c_str()] = talkWindow;
        windowManager.setCurrentWidget(talkWindow);
        talkWindow->setInfo(info);
        connect(talkWindow, &TalkWindow::signalNewMessage, this, &ChatListForm::onTalkNewMessage);

        QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
        item->setSizeHint(QSize(172, 74));
        // ui->listWidget->insertItem(0, item);
        ui->listWidget->addItem(item);
        ui->listWidget->setCurrentItem(item);

        ChatItem* chatItem = new ChatItem();
        chatItem->setName(info.name().c_str());
        chatItem->setUserId(info.userid().c_str());
        chatItem->setPixmap(info.headshot().c_str());
        chatItem->setMessage("", "");
        ui->listWidget->setItemWidget(item, chatItem);

        chatItems[info.userid().c_str()] = chatItem;
        items[info.userid().c_str()]     = item;

        auto& queueMessage = dendingMessages[info.userid().c_str()];
        while (!queueMessage.empty()) {
            auto msg = queueMessage.front();
            queueMessage.pop();
            talkWindow->onNewMessage(msg);
        }
    }
}

void ChatListForm::addNewChat(const data::ChatRoomInfo& info) {
    try {
        auto* talkWindow = talkWindows.at(info.roomid().c_str());
        windowManager.setCurrentWidget(talkWindow);
        auto* item = items[info.roomid().c_str()];
        ui->listWidget->setCurrentItem(item);
    }
    catch (const std::exception&) {
        auto talkWindow = windowManager.addSubWindow<TalkWindow>(info.roomid().c_str());
        talkWindow->setTitle(info.name().c_str());
        talkWindows[info.roomid().c_str()] = talkWindow;
        windowManager.setCurrentWidget(talkWindow);
        talkWindow->setInfo(info);

        connect(talkWindow, &TalkWindow::signalNewMessage, this, &ChatListForm::onTalkNewMessage);

        QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
        item->setSizeHint(QSize(172, 74));
        // ui->listWidget->insertItem(0, item);
        ui->listWidget->addItem(item);
        ui->listWidget->setCurrentItem(item);

        ChatItem* chatItem = new ChatItem();
        chatItem->setName(info.name().c_str());
        chatItem->setUserId(info.roomid().c_str());
        chatItem->setPixmap(info.headshot().c_str());
        chatItem->setMessage("", "");
        ui->listWidget->setItemWidget(item, chatItem);

        chatItems[info.roomid().c_str()] = chatItem;
        items[info.roomid().c_str()]     = item;

        auto& queueMessage = dendingMessages[info.roomid().c_str()];
        while (!queueMessage.empty()) {
            auto msg = queueMessage.front();
            queueMessage.pop();
            talkWindow->onNewMessage(msg);
        }
    }
}
